import axios from 'axios'
import qs from 'qs'
import store from '@/store'
import {refreshToken} from "@/api/user";
import {decodeJWT} from "@/utils/oAuth2Login";
import {logout} from "@/router";

function errorState(error, opts, url) {
    // 如果http状态码正常，则直接返回数据
    if (opts.discretion) { // 自行处理
        return false
    }
    if (error.response && (error.response.status === 403 || error.response.status === 401 || error.response.status === 407)) {

    } else if (error.response && error.response.status === 504) {

    } else {
        if (error && error.stack.indexOf('timeout') > -1) {

        } else {
            // 只出现一次时才有弹窗
            if (errStateCount === 0) {

            }
        }
    }
}

// 请求成功
function successState(res, opts) {
    // 统一判断后端返回的错误码
    const resData = res.data
    if (resData.code !== 200 && resData.code !== 503) {
        if (opts.discretion) { // 自行处理
            return false
        }
        if (resData.code === 401 || resData.code === 407) {

        } else if (resData.code === 403) {

        } else {

        }
    }
}

let errStateCount = 0
window.refreshTokenCheck = true
const Service = async (opts, data = {}) => {
    const headers = opts.headers || {}
    const timestamp = new Date().getTime()
    let transformRequest = null
    const token = opts.url.indexOf('webapi/auth/') >= 0 ? false : store.state.token
    if (token) {
        headers.Authorization = 'Bearer ' + token
    }
    headers.timestamp = timestamp
    if (opts.method === 'post' || opts.method === 'put' || opts.method === 'delete') {
        // 序列化
        if (headers['Content-Type'] === 'application/x-www-form-urlencoded;charset=utf-8') { // 普通表单提交的Content-Type
            opts.data = qs.stringify(opts.data)
        } else if (headers['Content-Type'] === 'multipart/form-data') { // 含有附件的表单提交的Content-Type 有附件
            transformRequest = [data => {
                if (data && typeof data === 'string') {
                    try {
                        data = JSON.parse(data.replace(/:\s*(\d{16,})(?=\s*[,\}])/g, ':"$1"'))
                    } catch (e) {
                        data = JSON.parse(data)
                    }
                }
                return data
            }]
        }
    }
    const httpDefaultOpts = { // http默认配置
        responseType: opts.responseType,
        method: opts.method,
        url: opts.url,
        timeout: opts.timeout || 6000000, // 前端10min延时控制
        params: opts.params,
        data: opts.data,
        headers: {
            ...headers
        },
        transformRequest
    }
    if (opts.method.toUpperCase() === 'GET') {
        delete httpDefaultOpts.data
    }
// 创建axios实例
    const promise = new Promise((resolve, reject) => {
        axios(httpDefaultOpts).then((res) => {
            successState(res, data, opts)
            resolve(res)
        }).catch((err) => {
            errorState(err, data, opts.url)
            reject(err)
        })
    })
    return promise
}

let isRefreshing = false

// 重试队列，每一项将是一个待执行的函数形式
let requests = []

axios.interceptors.response.use(response => {
    const {code} = response.data
    if (code === 401) {
        const config = response.config
        if (!isRefreshing) {
            isRefreshing = true
            const params = new URLSearchParams()
            params.append('refreshToken', store.state.refresh_token)
            return refreshToken(params).then(res => {
                if (res.data.hasOwnProperty('code') || res.data.id_token === null) {
                    logout()
                } else {
                    const {id_token: token, refresh_token,} = res.data
                    store.commit('SET_TOKEN', {token, refresh_token,}) // 后端接口调用 ，使用 id_token
                    store.commit('SET_USER_INFO', Object.assign(
                        store.state.userInfo, {exp: decodeJWT(res.data.id_token).exp}
                    ))
                    config.headers['Authorization'] = 'Bearer ' + token
                    requests.forEach(cb => cb(token))
                    requests = []
                    return axios(config)
                }
            }).catch(res => {
            }).finally(() => {
                isRefreshing = false
            })
        } else {
            // 正在刷新token，将返回一个未执行resolve的promise
            return new Promise((resolve) => {
                // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
                requests.push((token) => {
                    config.headers['Authorization'] = 'Bearer ' + token
                    resolve(axios(config))
                })
            })
        }
    }
    return response
}, error => {
    return Promise.reject()
})
export default Service
